package com.smasher.media

import android.content.Context
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.speech.tts.TextToSpeech.OnInitListener
import android.speech.tts.UtteranceProgressListener
import android.util.Log
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import java.util.Locale

/**
 * @author HXZ_Android
 */
class TTSHelper(
    context: Context,
    private val options: TTSOptions,
    private val initListener: TTSInitListener
) :
    DefaultLifecycleObserver {

    constructor(context: Context, initListener: TTSInitListener) : this(
        context,
        TTSOptions(),
        initListener
    )


    private var isInitSuccess: Boolean = false

    private var isSpeaking = false

    private val tts: TextToSpeech

    private val unsupportedError = context.getString(R.string.language_support_valid)

    private val unsupportedMissing = context.getString(R.string.language_support_missing)

    private val initError = context.getString(R.string.language_support_init_error)

    private val unknownError = context.getString(R.string.language_support_unknown)

    init {
        tts = TextToSpeech(context, OnInitListener { i: Int ->
            if (i == TextToSpeech.SUCCESS) { //设置语音
                initializeCoreComponents()
                initListener.onSuccess()
                isInitSuccess = true
            } else {
                initListener.onError(initError)
                isInitSuccess = false
            }
        })
    }


    /**
     * 通用配置初始化
     */
    private fun initializeCoreComponents() {
        val supportEngines = getSupportEngine()
        Log.d(TAG, "supportEngines: ${supportEngines.contentToString()}")
        val supportVoices = getSupportVoice()
        Log.d(TAG, "supportVoices: ${supportVoices.contentToString()}")

        //默认语音
        val voice = tts.defaultVoice
        //默认引擎
        val defaultEngine = tts.defaultEngine
        Log.i(TAG, "voice=${voice.name}  engine=$defaultEngine")

        //设置语速
        val speechRate = tts.setSpeechRate(options.speechRate)
        //设置语音音调
        val pitch = tts.setPitch(options.pitch)
        //设置侦听器
        tts.setOnUtteranceProgressListener(utteranceProgressListener)
        Log.i(TAG, "SpeechRate=$speechRate setPitchRet=$pitch")
    }


    fun attach(owner: LifecycleOwner) {
        owner.lifecycle.addObserver(this)
    }

    fun checkAndSetLanguage(callback: (Boolean, String) -> Unit) {
        val support1 = tts.isLanguageAvailable(options.language)
        if (support1 == TextToSpeech.LANG_AVAILABLE ||
            support1 == TextToSpeech.LANG_COUNTRY_AVAILABLE ||
            support1 == TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE
        ) {
            tts.setLanguage(options.language)
            callback.invoke(true, "")
            isInitSuccess = true
        } else if (support1 == TextToSpeech.LANG_MISSING_DATA) {
            callback.invoke(false, unsupportedMissing)
            isInitSuccess = false
        } else {
            callback.invoke(false, unsupportedError)
            isInitSuccess = false
        }
    }

    private val utteranceProgressListener: UtteranceProgressListener =
        object : UtteranceProgressListener() {
            /**
             * Called when an utterance "starts" as perceived by the caller. This will
             * be soon before audio is played back in the case of a [TextToSpeech.speak]
             * or before the first bytes of a file are written to the file system in the case
             * of [TextToSpeech.synthesizeToFile].
             *
             * @param utteranceId The utterance ID of the utterance.
             */
            override fun onStart(utteranceId: String?) {
                //播报开始
                isSpeaking = true
            }

            /**
             * Called when an utterance has successfully completed processing.
             * All audio will have been played back by this point for audible output, and all
             * output will have been written to disk for file synthesis requests.
             *
             *
             * This request is guaranteed to be called after [.onStart].
             *
             * @param utteranceId The utterance ID of the utterance.
             */
            override fun onDone(utteranceId: String?) {
                //播报结束
                isSpeaking = false
            }

            override fun onError(utteranceId: String?) {
                //播报出错
                isSpeaking = false
            }

            /**
             * Called when an error has occurred during processing. This can be called
             * at any point in the synthesis process. Note that there might be calls
             * to {@link #onStart(String)} for specified utteranceId but there will never
             * be a call to both {@link #onDone(String)} and {@link #onError(String,int)} for
             * the same utterance. The default implementation calls {@link #onError(String)}.
             *
             * @param utteranceId The utterance ID of the utterance.
             * @param errorCode one of the ERROR_* codes from {@link TextToSpeech}
             */
            override fun onError(utteranceId: String?, errorCode: Int) {
                //播报出错
                isSpeaking = false
            }
        }


    private fun getSupportEngine(): Array<String> {
        return tts.engines?.map { it.name }?.toTypedArray() ?: emptyArray()
    }

    private fun getSupportVoice(): Array<String> {
        return tts.voices?.map { it.name }?.toTypedArray() ?: emptyArray()
    }

    private fun setEngineByPackageName(packageName: String) {
        tts.setEngineByPackageName(packageName)
    }


    fun speakFlush(text: String) {
        speak(text, TextToSpeech.QUEUE_FLUSH)
    }

    fun speakAdd(text: String) {
        speak(text, TextToSpeech.QUEUE_ADD)
    }

    fun speakTest() {
        speak("语音播报已准备好！", TextToSpeech.QUEUE_FLUSH)
    }

    /**
     * 播报
     *
     * @param text      文本
     * @param queueMode 队列模式
     * @return result
     */
    private fun speak(text: String, queueMode: Int): Int {
        if (!isInitSuccess) {
            return SPEAKING_RESULT_INIT_FAILED
        }

        if (isSpeaking) {
            return SPEAKING_RESULT_SPEAKING
        }

        val utteranceId = createUtteranceId()
        val bundle = Bundle().apply {
            //utterance，这个参数随便写，用于监听播报完成的回调中
            putString(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, utteranceId)
            //音量
            putFloat(TextToSpeech.Engine.KEY_PARAM_VOLUME, options.volume)
            //播放类型
            putInt(TextToSpeech.Engine.KEY_PARAM_STREAM, options.streamType)
        }

        val ret = tts.speak(text, queueMode, bundle, utteranceId)
        return if (ret == TextToSpeech.SUCCESS) {
            //播报成功
            SPEAKING_RESULT_SUCCESS
        } else {
            SPEAKING_RESULT_SPEAK_ERROR
        }
    }


    private fun createUtteranceId(): String {
        val timestamp = System.nanoTime() // 纳秒级时间戳
        val random = (Math.random() * 9000 + 1000).toInt() // 4位随机数
        return "$timestamp-$random"
    }

    fun release() {
        isInitSuccess = false
        tts.stop()
        tts.shutdown()
    }

    override fun onDestroy(owner: LifecycleOwner) {
        release()
    }


    companion object {
        const val TAG: String = "TTSHelper"

        const val SPEAKING_RESULT_SUCCESS = 0
        const val SPEAKING_RESULT_INIT_FAILED = -1
        const val SPEAKING_RESULT_SPEAKING = -2
        const val SPEAKING_RESULT_SPEAK_ERROR = -3
    }
}
